package com.polaris.live.manager

import android.app.Activity
import androidx.activity.ComponentActivity
import androidx.annotation.MainThread
import androidx.core.os.bundleOf
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import com.android.billingclient.api.BillingClient
import com.android.billingclient.api.BillingClientStateListener
import com.android.billingclient.api.BillingFlowParams
import com.android.billingclient.api.BillingResult
import com.android.billingclient.api.ProductDetails
import com.android.billingclient.api.Purchase
import com.android.billingclient.api.PurchasesUpdatedListener
import com.android.billingclient.api.QueryProductDetailsParams
import com.android.billingclient.api.QueryPurchasesParams
import com.android.billingclient.api.queryProductDetails
import com.android.billingclient.api.queryPurchasesAsync
import com.blankj.utilcode.util.AppUtils
import com.blankj.utilcode.util.EncryptUtils
import com.blankj.utilcode.util.NetworkUtils
import com.blankj.utilcode.util.Utils
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.ktx.Firebase
import com.lxj.xpopup.XPopup
import com.polaris.live.App
import com.polaris.live.common.cacha.CacheUtil
import com.polaris.live.common.cacha.UserManager
import com.polaris.live.common.constant.CommonConst.ErrorCode.PAY_FAILURE_FLUSHED
import com.polaris.live.common.constant.ServerConfig
import com.polaris.live.common.manager.CoroutineScopeManager
import com.polaris.live.common.manager.withRetry
import com.polaris.live.common.manager.withRetryNow
import com.polaris.live.common.network.AppException
import com.polaris.live.common.network.getSuccessResult
import com.polaris.live.common.util.LogExt
import com.polaris.live.common.util.StructUtils
import com.polaris.live.common.util.ToastGravity
import com.polaris.live.common.util.loading.LoadingUtils
import com.polaris.live.constant.EventConst
import com.polaris.live.constant.TrackEventConst.EVENT_IFINFORM
import com.polaris.live.constant.TrackEventConst.EVENT_PAY_ERROR
import com.polaris.live.constant.TrackEventConst.EVENT_PAY_PC
import com.polaris.live.constant.TrackEventConst.EVENT_SDKPAGE_PV
import com.polaris.live.constant.TrackEventConst.GOOGLE_PAY_SDK_PAGE
import com.polaris.live.constant.TrackEventConst.IFINFORM_PAGE
import com.polaris.live.constant.TrackEventConst.INFORM
import com.polaris.live.constant.TrackEventConst.PARAMS_PAY_CANCEL
import com.polaris.live.constant.TrackEventConst.PARAMS_PAY_FAIL
import com.polaris.live.constant.TrackEventConst.PARAMS_PAY_SUCCESS
import com.polaris.live.constant.TrackEventConst.TRACK_DIALOG
import com.polaris.live.constant.UserConst.FromType
import com.polaris.live.dialog.TestChargeDialog
import com.polaris.live.im.db.database.AppDatabase
import com.polaris.live.im.db.entity.PurchaseOrderEntity
import com.polaris.live.im.db.entity.PurchasePretreatmentEntity
import com.polaris.live.net.payerService
import com.polaris.live.resp.go_resp.GooglePlayTestVerifyBean
import com.polaris.live.resp.go_resp.GooglePlayVerifyBean
import com.polaris.live.resp.go_resp.RechargePrepareBean
import com.polaris.live.translation.R.string
import com.polaris.live.utils.TrackHelper
import com.polaris.live.utils.postEvent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.concurrent.TimeUnit

/**
 * GooglePayManager
 *
 * @author Created by lucas on 2023/11/22 13:42
 */
object GooglePayManager {

    const val TAG = "Google"

    init {
        //监听前后台状态
        AppUtils.registerAppStatusChangedListener(object : Utils.OnAppStatusChangedListener {
            override fun onForeground(activity: Activity?) {
                queryPurchaseHistory()
            }

            override fun onBackground(activity: Activity?) {
            }
        })
        //监听网络状态
        NetworkUtils.registerNetworkStatusChangedListener(object : NetworkUtils.OnNetworkStatusChangedListener {
            override fun onConnected(networkType: NetworkUtils.NetworkType?) {
                if (isDetecting) {
                    return
                }

                isDetecting = true

                CoroutineScopeManager.mainScope.launch {
                    (0 until 3).forEach {
                        delay(it * 1000 + 3000L)
                        queryPurchaseHistory()
                    }

                    isDetecting = false
                }
            }

            override fun onDisconnected() {
            }
        })
    }

    @Volatile
    private var isDetecting = false

    @Volatile
    private var client: BillingClient? = null

    /**
     * 获取BillingClient
     */
    fun getClient(): BillingClient {
        return client ?: synchronized(this) {
            client ?: newBillingClient()
                .apply {
                    client = this
                }
        }
    }

    private fun newBillingClient() = BillingClient.newBuilder(App.instance)
        .enablePendingPurchases()
        .setListener(mPurchasesUpdateListener)
        .build()

    private val mClientStateListener = object : BillingClientStateListener {

        override fun onBillingSetupFinished(billingResult: BillingResult) {
            LogExt.logI(TAG, "google pay connect result : $billingResult")

            when (billingResult.responseCode) {
                //连接google pay成功
                BillingClient.BillingResponseCode.OK -> {
                    queryPurchaseHistory()

                    mRetryConnectNum = 0
                }

                BillingClient.BillingResponseCode.SERVICE_DISCONNECTED -> {
                    retryConnectGoogle()
                }

                else -> {
                    LogExt.logI(TAG, billingResult.debugMessage)
                }
            }
        }

        override fun onBillingServiceDisconnected() {
            //丢失连接，可做重连处理
            LogExt.logI(TAG, "google pay connect fail")

            retryConnectGoogle(true)
        }
    }

    private const val VERIFY_RETRY_MAX = 15

    private var mRetryConnectNum = 0
    private var mClientConnecting: Boolean = false

    /**
     * 记录当前的与请求订单，这里只是用来增加速度
     */
    private var mPurchasePretreatmentEntity: PurchasePretreatmentEntity? = null

    /**
     * 当前正在购买的商品id
     */
    private val mCurrentProductIds = mutableMapOf<Int, String>()

    private val mOnPurchaseListeners = StructUtils.newSaleSet<OnPurchaseListener>()

    private suspend fun onPurchaseSuccess(productId: String) {
        withContext(CoroutineScopeManager.mainDispatcher) {
            mOnPurchaseListeners.forEach {
                it.onPurchaseSuccess(productId)
            }
        }
    }

    private suspend fun onPurchaseFailure(productId: String, t: AppException?) {
        withContext(CoroutineScopeManager.mainDispatcher) {
            mOnPurchaseListeners.forEach {
                it.onPurchaseFailure(productId, t)
            }
        }
    }

    fun init() {
        startConnect()

        GlobalScope.launch(CoroutineScopeManager.ioDispatcher) {
            //这里清除5天前的数据，冗余2天
            AppDatabase.instance.purchasePretreatmentEntityDao()
                .clearRedundancy(CacheUtil.getServerTime() - TimeUnit.DAYS.toMillis(5))
            AppDatabase.instance.purchaseOrderEntityDao()
                .clearRedundancy(CacheUtil.getServerTime() - TimeUnit.DAYS.toMillis(5))
        }
    }

    fun login() {
        queryPurchaseOrder()
        queryPurchaseHistory()
    }

    private fun startConnect() {
        getClient().startConnection(mClientStateListener)

        mClientConnecting = false
    }

    private fun retryConnectGoogle(forceConnect: Boolean = false) {
        val state = getClient().connectionState
        when {
            //client已经失效则重连
            state == BillingClient.ConnectionState.CLOSED -> {
                LogExt.logI(TAG, "Google pay closed")

                client = newBillingClient()
                startConnect()
                return
            }

            //连接中无视
            !forceConnect && state == BillingClient.ConnectionState.CONNECTING -> {
                LogExt.logI(TAG, "Google pay connecting")

                return
            }

            //已连接无视
            !forceConnect && state == BillingClient.ConnectionState.CONNECTED -> {
                LogExt.logI(TAG, "Google pay connected")

                return
            }

            else -> {
                if (mClientConnecting) {
                    return
                }

                mClientConnecting = true

                CoroutineScope(CoroutineScopeManager.ioDispatcher).launch {
                    delay(1000)

                    startConnect()

                    LogExt.logI(TAG, "Google pay connect fail retry: $mRetryConnectNum times")
                }
            }
        }
    }

    //---------- 业务逻辑

    //购买更新回调
    private val mPurchasesUpdateListener = PurchasesUpdatedListener { billingResult, list ->
        if (billingResult.responseCode == BillingClient.BillingResponseCode.OK && !list.isNullOrEmpty()) {
            LogExt.logI(TAG, "Google pay success")

            CoroutineScopeManager.ioScope.launch {
                list.forEach {
                    handelPurchase(it)
                }
            }
        } else if (billingResult.responseCode == BillingClient.BillingResponseCode.USER_CANCELED) {
            // Handle an error caused by a user cancelling the purchase flow.
            LogExt.logI(TAG, "Google pay cancel")

            CoroutineScopeManager.mainScope.launch {
                onPurchaseFailure(list?.firstOrNull()?.products?.firstOrNull() ?: "", null)
            }
        } else {
            // Handle any other error codes.
            LogExt.logI(TAG, "Google pay error")

            googlePayFailure("googleError", billingResult)

            CoroutineScopeManager.mainScope.launch {
                onPurchaseFailure(
                    list?.firstOrNull()?.products?.firstOrNull() ?: "",
                    AppException(
                        errCode = billingResult.responseCode,
                        error = billingResult.debugMessage
                    )
                )
            }
        }
    }

    private fun googlePayFailure(errType: String, billingResult: BillingResult) {
        googlePayFailure(errType, billingResult.responseCode, billingResult.debugMessage)
    }

    /**
     * 购买商品
     */
    fun buyShow(
        activity: ComponentActivity,
        productId: String,
        @FromType fromType: Int,
        payerRechargeRewardsType: Int = 0,
        objectId: Long? = null,
        price: String,
        showToast: Boolean = true,
        onSuccess: (() -> Unit)? = null,
        onFailure: ((t: AppException?) -> Unit)? = null,
    ) {
        if (ServerConfig.isDebug()
            && !ServerConfig.isProdServer()
            && !ServerConfig.isPreServer()
        ) {
            buyTest(
                activity,
                productId,
                fromType,
                payerRechargeRewardsType,
                objectId,
                { onSuccess?.invoke() },
                { _, t -> onFailure?.invoke(t) }
            )
            return
        }

        LoadingUtils.showLoadingDialog(message = string.recharge_loading, cancelable = true)

        mCurrentProductIds[onSuccess.hashCode()] = productId

        buy(activity, productId, fromType, payerRechargeRewardsType, objectId, {
            if (it == productId || mCurrentProductIds[onSuccess.hashCode()] == productId) {
                onSuccess?.invoke()

                TrackHelper.postTrack(
                    GOOGLE_PAY_SDK_PAGE, EVENT_PAY_PC,
                    params = mutableMapOf(
                        "buttonsource" to price,
                        "status" to PARAMS_PAY_SUCCESS
                    )
                )

                ToastGravity.showGravity(string.recharge_success)
            }

            mCurrentProductIds.remove(onSuccess.hashCode())

            LoadingUtils.dismissLoadingDialog()
        }, { id, t ->
            if (id == productId || mCurrentProductIds[onSuccess.hashCode()] == productId) {
                onFailure?.invoke(t)

                if (t is AppException) {
                    if (t.errCode != PAY_FAILURE_FLUSHED) {
                        TrackHelper.postTrack(
                            GOOGLE_PAY_SDK_PAGE, EVENT_PAY_PC,
                            params = mutableMapOf(
                                "buttonsource" to price,
                                "status" to PARAMS_PAY_FAIL
                            )
                        )
                        if (showToast) {
                            ToastGravity.showGravity(t.message)
                        }
                    }
                } else {
                    TrackHelper.postTrack(
                        GOOGLE_PAY_SDK_PAGE, EVENT_PAY_PC,
                        params = mutableMapOf(
                            "buttonsource" to price,
                            "status" to PARAMS_PAY_CANCEL
                        )
                    )
                    if (showToast) {
                        ToastGravity.showGravity(string.recharge_cancel)
                    }
                }
            }

            mCurrentProductIds.remove(onSuccess.hashCode())

            LoadingUtils.dismissLoadingDialog()
        })
    }

    private fun buyTest(
        activity: ComponentActivity,
        productId: String,
        fromType: Int,
        payerRechargeRewardsType: Int,
        objectId: Long? = null,
        onSuccess: (productId: String) -> Unit,
        onFailure: (productId: String, t: AppException?) -> Unit,
    ) {
        XPopup.Builder(activity)
            .isDestroyOnDismiss(true)
            .asCustom(TestChargeDialog(activity) {
                LoadingUtils.showLoadingDialog(message = string.recharge_loading)

                CoroutineScopeManager.mainScope.launch {
                    try {
                        val resp = payerService.rechargePrepare(
                            RechargePrepareBean(
                                productId,
                                payerRechargeRewardsType,
                                fromType,
                                objectId
                            )
                        )
                        val bean = resp.getSuccessResult()
                            ?: throw AppException(resp.code, resp.errorMessage)

                        val payResp = payerService.testCharge(
                            GooglePlayTestVerifyBean(
                                productId,
                                payerRechargeRewardsType,
                                fromType,
                                objectId,
                                bean.token
                            )
                        )
                        if (payResp.isSuccess()) {
                            onSuccess(productId)
                        } else {
                            throw AppException(payResp.code, payResp.errorMessage)
                        }
                    } catch (t: AppException) {
                        onFailure(productId, t)
                        if (t.errCode != PAY_FAILURE_FLUSHED) {
                            ToastGravity.showGravity(t.message)
                        }
                    } finally {
                        LoadingUtils.dismissLoadingDialog()
                    }
                }

            })
            .show()
    }

    /**
     * 购买商品
     *
     * @param activity Activity
     * @param productId 商品id
     * @param fromType 来源类型
     * @param payerRechargeRewardsType 充值奖励类型
     * @param objectId 对象id
     * @param onSuccess 成功监听
     * @param onFailure 失败监听
     */
    fun buy(
        activity: ComponentActivity,
        productId: String,
        fromType: Int,
        payerRechargeRewardsType: Int,
        objectId: Long? = null,
        onSuccess: (productId: String) -> Unit,
        onFailure: (productId: String, t: AppException?) -> Unit,
    ) {
        if (activity.lifecycle.currentState == Lifecycle.State.DESTROYED) {
            return
        }

        val onPurchaseListener = object : OnPurchaseListener {
            override fun onPurchaseSuccess(productId: String) {
                onSuccess(productId)
            }

            override fun onPurchaseFailure(productId: String, t: AppException?) {
                onFailure(productId, t)
            }
        }

        activity.lifecycle.addObserver(object : LifecycleEventObserver {
            override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
                if (event == Lifecycle.Event.ON_DESTROY) {
                    mOnPurchaseListeners.remove(onPurchaseListener)
                }
            }
        })

        mOnPurchaseListeners.add(object : OnPurchaseListener {
            override fun onPurchaseSuccess(productId: String) {
                onPurchaseListener.onPurchaseSuccess(productId)

                mOnPurchaseListeners.remove(this)
            }

            override fun onPurchaseFailure(productId: String, t: AppException?) {
                onPurchaseListener.onPurchaseFailure(productId, t)

                mOnPurchaseListeners.remove(this)
            }
        })

        Firebase.analytics.postEvent(
            EventConst.RECHARGE_START, bundleOf(
                "recharge_type" to "google_pay",
                "product_id" to productId,
                "from_type" to fromType,
                "rewards_type" to payerRechargeRewardsType,
                "object_id" to objectId,
            )
        )

        CoroutineScopeManager.ioScope.launch {
            try {
                invokeBuy(activity, productId, fromType, payerRechargeRewardsType, objectId)
            } catch (t: AppException) {
                onPurchaseFailure(productId, t)
            }
        }
    }

    /**
     * @throws GooglePayException 如果任意一步不是[BillingClient.BillingResponseCode.OK]
     */
    private suspend fun invokeBuy(
        activity: Activity,
        productId: String,
        fromType: Int,
        payerRechargeRewardsType: Int,
        objectId: Long? = null,
    ) {
        withContext(CoroutineScopeManager.ioDispatcher) {
            val resp =
                payerService.rechargePrepare(
                    RechargePrepareBean(
                        productId,
                        payerRechargeRewardsType,
                        fromType,
                        objectId
                    )
                )
            val bean = resp.getSuccessResult()
            if (bean == null) {
                withContext(CoroutineScopeManager.mainDispatcher) {
                    onPurchaseFailure(productId, AppException(resp.code, resp.errorMessage))
                }
                return@withContext
            }

            savePurchasePretreatment(productId, bean.token)

            val productDetail = queryProduct(productId)

            val productDetailsParamsList = listOf(
                BillingFlowParams.ProductDetailsParams.newBuilder()
                    .setProductDetails(productDetail)
                    .build()
            )

            val billingFlowParams = BillingFlowParams.newBuilder()
                .setObfuscatedAccountId(
                    EncryptUtils.encryptSHA256ToString(
                        UserManager.getUserId().toString()
                    )
                )
                .setObfuscatedProfileId(EncryptUtils.encryptSHA256ToString(UserManager.getUser().device?.uniqueId))
                .setProductDetailsParamsList(productDetailsParamsList)
                .build()

            val result = getClient().launchBillingFlow(activity, billingFlowParams)
            if (!result.isSuccess()) {
                googlePayFailure("launchError", result)

                throw GooglePayException(result.responseCode, result.debugMessage)
            } else {
                //成功拉起sdk上传数据
                Firebase.analytics.postEvent(EventConst.RECHARGE_INITIATE)
                TrackHelper.postTrack(GOOGLE_PAY_SDK_PAGE, EVENT_SDKPAGE_PV, TRACK_DIALOG)
            }
        }
    }

    private suspend fun queryProduct(productId: String): ProductDetails {
        val queryProductDetailsParams =
            QueryProductDetailsParams.newBuilder()
                .setProductList(
                    listOf(
                        QueryProductDetailsParams.Product.newBuilder()
                            .setProductId(productId)
                            .setProductType(BillingClient.ProductType.INAPP)
                            .build()
                    )
                )
                .build()

        val (result, list) = getClient().queryProductDetails(queryProductDetailsParams)
        if (result.isSuccess()) {
            return list?.find { it.productId == productId } ?: throw GooglePayException(
                -1,
                "productDetails is null"
            )
        }

        throw GooglePayException(result.responseCode, result.debugMessage)
    }

    private fun queryPurchaseOrder() {
        CoroutineScopeManager.ioScope.launch {
            AppDatabase.instance.purchaseOrderEntityDao().findByUserId(UserManager.getUserId())
                .forEach {
                    try {
                        reportToServer(it)
                    } catch (_: AppException) {
                    }
                }
        }
    }

    private fun queryPurchaseHistory() {
        if (!UserManager.isLogin()) {
            return
        }
        CoroutineScopeManager.ioScope.launch {
            val params = QueryPurchasesParams.newBuilder()
                .setProductType(BillingClient.ProductType.INAPP)
                .build()

            val (result, list) = getClient().queryPurchasesAsync(params)
            if (result.isSuccess() && list.isNotEmpty()) {
                list.forEach {
                    try {
                        handelPurchase(it)
                    } catch (_: AppException) {
                    }
                }
            }
        }
    }

    private suspend fun handelPurchase(purchase: Purchase) {
        LogExt.logI(TAG, "Google pay purchase: $purchase")

        if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED && !purchase.isAcknowledged) {
            val productId = purchase.products.firstOrNull()
            if (productId == null) {
                LogExt.logI(TAG, "Google pay purchase failure: $purchase")
                return
            }

            val orderId = purchase.orderId
            val pretreatment = purchase.accountIdentifiers?.obfuscatedAccountId?.let {
                findPurchasePretreatment(it, productId)
            }

            val order = savePurchaseOrder(purchase, productId, orderId, pretreatment)

            reportToServer(order)
        }
    }

    private suspend fun reportToServer(order: PurchaseOrderEntity) {
        val bean = GooglePlayVerifyBean(
            order.productId,
            order.purchaseToken,
            order.orderId,
            order.token
        )

        try {
            val res = withRetry(VERIFY_RETRY_MAX) {
                val response = payerService.googleVerify(bean)
                response.getSuccessResult() ?: throw AppException(response.code, response.errorMessage)
            }

            GlobalScope.launch {
                val price = fetchPrice(order.productId)

                val data = bundleOf(
                    FirebaseAnalytics.Param.CURRENCY to "USD",
                    FirebaseAnalytics.Param.VALUE to price
                )

                //调用后端接口成功上报
                if (res.successRecharge) {
                    Firebase.analytics.postEvent(EventConst.SUCCESSFUL_RECHARGE, data)
                    Firebase.analytics.postEvent(EventConst.SUCCESSFUL_RECHARGE_3_A, data)
                    Firebase.analytics.postEvent(EventConst.SUCCESSFUL_RECHARGE_3_B, data)
                    Firebase.analytics.postEvent(EventConst.SUCCESSFUL_RECHARGE_3_C, data)
                    TrackHelper.postTrack(IFINFORM_PAGE, EVENT_IFINFORM, INFORM)
                }

                //这里保留一个重复上报的，用于数据对比
                Firebase.analytics.postEvent(EventConst.SUCCESSFUL_RECHARGE_REPEAT, data)

                if (res.firstRechargeZoneId0) {
                    Firebase.analytics.postEvent(EventConst.SUCCESSFUL_RECHARGE_FIRST, data)
                }
                if (res.newRechargeZoneId0) {
                    Firebase.analytics.postEvent(EventConst.SUCCESSFUL_RECHARGE_NEW, data)
                }
                if (res.firstRechargeZoneId8) {
                    Firebase.analytics.postEvent(EventConst.SUCCESSFUL_RECHARGE_FIRST_8, data)
                }
                if (res.newRechargeZoneId8) {
                    Firebase.analytics.postEvent(EventConst.SUCCESSFUL_RECHARGE_NEW_8, data)
                }

                if (!res.fireBaseEvent.isNullOrEmpty()) {
                    res.fireBaseEvent.forEach {
                        Firebase.analytics.postEvent(it, data)
                    }
                }
            }

            deletePurchaseOrder(order)

            onPurchaseSuccess(order.productId)

            LogExt.logI(TAG, "Google pay consume success: $order")
        } catch (t: AppException) {
            LogExt.logE(TAG, "Google pay consume failure", t)

            googlePayFailure("serverError", t.errCode, t.errorMsg)

            withContext(CoroutineScopeManager.mainDispatcher) {
                onPurchaseFailure(order.productId, t)

                showRechargeFailDialog()
            }
        }
    }

    private suspend fun fetchPrice(productId: String): Double {
        return try {
            withRetryNow {
                val resp = payerService.getPrice(productId)
                resp.getSuccessResult()
                    ?: throw AppException(resp.code, resp.errorMessage)
            }
        } catch (_: Throwable) {
            getPriceFromSku(productId)
        }
    }

    /**
     * 从sku获取价格
     */
    private fun getPriceFromSku(sku: String?): Double {
        var price = 0.0
        if (!sku.isNullOrEmpty()) {
            val temp = sku.split("_").toTypedArray()
            price = try {
                val priceStr = temp[1]
                priceStr.toDouble()
            } catch (e: Exception) {
                e.printStackTrace()
                0.0
            }
        }
        return price
    }

    private suspend fun savePurchasePretreatment(productId: String, token: String) {
        val accountId = EncryptUtils.encryptSHA256ToString(UserManager.getUserId().toString())
        val pretreatmentEntity =
            PurchasePretreatmentEntity(
                null,
                accountId,
                productId,
                token,
                System.currentTimeMillis()
            )

        mPurchasePretreatmentEntity = pretreatmentEntity

        AppDatabase.instance.purchasePretreatmentEntityDao().save(pretreatmentEntity)
    }

    private suspend fun findPurchasePretreatment(
        accountId: String,
        productId: String,
    ): PurchasePretreatmentEntity? {
        val currentPurchasePretreatment = mPurchasePretreatmentEntity
        if (currentPurchasePretreatment != null
            && currentPurchasePretreatment.accountId == accountId
            && currentPurchasePretreatment.productId == productId
        ) {
            mPurchasePretreatmentEntity = null
            return currentPurchasePretreatment
        }

        return AppDatabase.instance.purchasePretreatmentEntityDao()
            .findByAccountIdAndProductId(accountId, productId)
    }

    private suspend fun savePurchaseOrder(
        purchase: Purchase,
        productId: String,
        orderId: String?,
        entity: PurchasePretreatmentEntity?,
    ): PurchaseOrderEntity {
        return PurchaseOrderEntity(
            null,
            UserManager.getUserId(),
            purchase.packageName,
            productId,
            purchase.purchaseToken,
            purchase.purchaseTime,
            purchase.purchaseState,
            orderId,
            entity?.token,
            System.currentTimeMillis()
        ).apply {
            AppDatabase.instance.purchaseOrderEntityDao().save(this)
        }
    }

    private suspend fun deletePurchaseOrder(entity: PurchaseOrderEntity) {
        AppDatabase.instance.purchaseOrderEntityDao().delete(entity.purchaseToken)
        entity.token?.also {
            AppDatabase.instance.purchasePretreatmentEntityDao().delete(it)
        }
    }

    private fun showRechargeFailDialog() {
        ToastGravity.showGravity("Google pay consume fail")
    }

    private fun googlePayFailure(errType: String, code: Int?, error: String?) {
        Firebase.analytics.postEvent(
            EventConst.RECHARGE_FAILURE,
            bundleOf(
                "recharge_type" to "google_pay",
                "errType" to errType,
                "errCode" to code,
                "error" to error
            )
        )

        TrackHelper.postTrack(
            GOOGLE_PAY_SDK_PAGE,
            EVENT_PAY_ERROR,
            TRACK_DIALOG,
            buildMap {
                put("recharge_type", "google_pay")
                put("errType", errType)
                if (code != null) {
                    put("errCode", code.toString())
                }
                if (error != null) {
                    "error" to error
                }
            }
        )
    }
}

fun BillingResult.isSuccess(): Boolean {
    return responseCode == BillingClient.BillingResponseCode.OK
}

class GooglePayException(
    val responseCode: Int,
    message: String,
) : Exception(message)

/**
 * 购买监听
 */
interface OnPurchaseListener {

    /**
     * 购买成功
     */
    @MainThread
    fun onPurchaseSuccess(productId: String)

    /**
     * 购买失败
     *
     * @param productId 购买的商品id
     * @param t 异常如果为空说明是取消
     */
    @MainThread
    fun onPurchaseFailure(productId: String, t: AppException?)

}